package com.fengyunhe.manager.service.impl;

import com.fengyunhe.common.ManagementNode;
import com.fengyunhe.common.ModulePermission;
import com.fengyunhe.common.bean.PageList;
import com.fengyunhe.manager.AppException;
import com.fengyunhe.manager.CurrentUser;
import com.fengyunhe.manager.UserStatus;
import com.fengyunhe.manager.dao.AdminRoleDao;
import com.fengyunhe.manager.dao.AdminUserRoleBindDao;
import com.fengyunhe.manager.dao.entity.AdminRoleEntity;
import com.fengyunhe.manager.dao.entity.AdminUserEntity;
import com.fengyunhe.common.AppContext;
import com.fengyunhe.common.bean.Page;
import com.fengyunhe.common.bean.Page.Offset;
import com.fengyunhe.common.bean.TreeNode;
import com.fengyunhe.common.bean.UserSimpleVo;
import com.fengyunhe.manager.dao.AdminUserDao;
import com.fengyunhe.manager.dao.entity.AdminUserRoleBindEntity;
import com.fengyunhe.manager.service.AdminUserService;
import com.fengyunhe.manager.vo.AdminUserVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;

@Service
public class AdminUserServiceImpl implements AdminUserService {

    Logger log = LoggerFactory.getLogger(AdminUserServiceImpl.class);

    @Resource
    private AdminUserDao adminUserDao;
    @Autowired
    private AdminRoleDao adminRoleDao;
    @Autowired
    private AdminUserRoleBindDao adminUserRoleBindDao;


    @Override
    public AdminUserVo getAdminUserByLoginName(String email) {

        String hql = "select new "
                + AdminUserVo.class.getName()
                + "("
                + "u.userId,u.userType,u.email,u.password,u.nickname,u.openId,"
                + "u.realName,u.phone,u.gender,u.status,u.lastLoginIp,u.superman,u.createdAt,"
                + "u.createdByUserId,u.createdByRealName"
                + ")"
                + " from AdminUserEntity as u where u.email = ?";

        AdminUserVo adminUserVo = adminUserDao.getUniqueResult(
                AdminUserVo.class, hql.toString(), email);
        return adminUserVo;
    }

    @Override
    public Integer addAdminUser(AdminUserVo user) throws Exception {
        // 检查账号是否已经存在
        boolean exist = this.adminUserDao.isExist("email", user.getEmail());

        if (exist) {
            throw new AppException("email是一个已经存在的账号");
        }

        AdminUserEntity u = new AdminUserEntity();
        u.setEmail(user.getEmail());
        u.setPassword(this.encryptPassword(u.getEmail(), user.getPassword()));
        u.setRealName(user.getRealName());
//            这里给超级用户标记为0，表示不是超级用户，超级用户不能通过界面添加
        u.setSuperman(0);
        u.setStatus(user.getStatus());
        u.setCreatedAt(new Timestamp(System.currentTimeMillis()));
        u.setGender(user.getGender());
        u.setUserType(user.getUserType());
        u.setLastLoginIp(user.getLastLoginIp());
        u.setNickname(user.getNickname());
        u.setCreatedByRealName(CurrentUser.get().getRealName());
        u.setCreatedByUserId(CurrentUser.get().getUserId());
        u.setPhone(user.getPhone());
        this.adminUserDao.save(u);
        return u.getUserId();

    }

    @Override
    public boolean updateAdminUser(AdminUserVo user) throws Exception {

        AdminUserEntity u = this.adminUserDao.loadById(user.getUserId());
        if (StringUtils.isNotBlank(user.getPassword())) { // 设置新密码
            u.setPassword(this.encryptPassword(u.getEmail(),
                    user.getPassword()));
        }
//            u.setEmail(user.getEmail());
        u.setRealName(user.getRealName());
        u.setStatus(user.getStatus());
        u.setCreatedAt(new Timestamp(System.currentTimeMillis()));
        u.setGender(user.getGender());
//            u.setUserType(user.getUserType());
        u.setLastLoginIp(user.getLastLoginIp());
        u.setNickname(user.getNickname());
        u.setCreatedByRealName(CurrentUser.get().getRealName());
        u.setCreatedByUserId(CurrentUser.get().getUserId());
        u.setPhone(user.getPhone());

        adminUserDao.update(u);
        return true;

    }


    @Override
    public boolean deleteAdminUser(Integer userId) throws Exception {
        try {
            adminUserDao.deleteById(userId);
        } catch (Exception e) {
            return false;
        }
        return true;
    }


    @Override
    public PageList<AdminUserVo> getUserPageListByRoleId(Integer roleId,
                                                         Page page) throws Exception {

        String hql = "select new "
                + AdminUserVo.class.getName()
                + "("
                + "u.userId,u.userType,u.email,u.password,u.nickname,u.openId,"
                + "u.realName,u.phone,u.gender,u.status,u.lastLoginIp,u.superman,u.createdAt,"
                + "u.createdByUserId,u.createdByRealName"
                + ")"
                + " from AdminUserEntity as u where u.superman=0 and u.userId in (SELECT s.adminUserByUserId.userId FROM AdminUserRoleBindEntity s WHERE s.adminRoleByRoleId.roleId=? ) ";

        PageList<AdminUserVo> pageList = adminUserDao.findPageList(page,
                AdminUserVo.class, hql.toString(), roleId);

        return pageList;
    }

    /**
     * 通过角色查询用户
     * @param roleId
     * @param usertype
     * @param keywords
     * @param page
     * @return
     * @throws Exception
     */
    @Override
    public PageList<AdminUserVo> getUserPageListByRoleId(Integer roleId, String usertype,String keywords, Page page) throws Exception {
        String hql = "select new "
                + AdminUserVo.class.getName()
                + "("
                + "u.userId,u.userType,u.email,u.password,u.nickname,u.openId,"
                + "u.realName,u.phone,u.gender,u.status,u.lastLoginIp,u.superman,u.createdAt,"
                + "u.createdByUserId,u.createdByRealName"
                + ")"
                + " from AdminUserEntity as u where u.superman=0 " ;
                List<Object> params = new ArrayList();
                if (StringUtils.isNotEmpty(keywords)) {
                    hql += " and u.realName like ?";
                    params.add("%" + keywords + "%");
                } else if (StringUtils.isNotEmpty(usertype)) {
                    hql += " and u.userType=?";
                    params.add(Integer.valueOf(usertype));
                }
                if(roleId!=null){
                    hql+="and u.userId in (SELECT s.adminUserByUserId.userId FROM AdminUserRoleBindEntity s WHERE s.adminRoleByRoleId.roleId=? ) ";
                    params.add(roleId);
                }

        PageList<AdminUserVo> pageList = adminUserDao.findPageList(page,
                AdminUserVo.class, hql.toString(), params.toArray());
        return pageList;
    }

    /**
     * 获取用户有权限的functionCode
     */
    @Override
    public Set<String> getUserPerms(int uid) {

        String hql = "select rp.perm from AdminRolePermBindEntity rp where rp.adminRoleByRoleId.roleId IN (" +
                "select ru.adminRoleByRoleId.roleId from AdminUserRoleBindEntity as ru where ru.adminUserByUserId.userId = ?) ";

        List<String> list = this.adminUserDao.findList(String.class, hql, uid);

        if (list == null || list.size() == 0) {
            return null;
        }
        Set<String> set = new HashSet<String>(list);
        return set;
    }


    @Override
    public List<Integer> getRoleIdListByAdminUserId(Integer userId) {
        String hql = "select adminRoleByRoleId.roleId from AdminUserRoleBindEntity where adminUserByUserId.userId = ?";
        List<Integer> roleIdList = this.adminRoleDao.findList(Integer.class, hql, userId);
        return roleIdList;
    }


    @Override
    public List<TreeNode> getAdminTreeNodes(Subject subject) {

        List<ManagementNode> managementNodeList = AppContext.getManagementNodeList();
        List<TreeNode> nodes = new ArrayList<TreeNode>();
        for (ManagementNode module : managementNodeList) {
            List<TreeNode> treeNode = checkPermAndConvertManagementNodeToTreeNode(module);
            if (treeNode != null) {
                nodes.addAll(treeNode);
            }
        }
        return nodes;
    }


    /**
     * 检查权限并递归转换管理模块为菜单
     *
     * @param managementNode
     * @return
     */
    private List<TreeNode> checkPermAndConvertManagementNodeToTreeNode(ManagementNode managementNode) {
        List<TreeNode> result = new ArrayList<TreeNode>();
        Subject subject = SecurityUtils.getSubject();
        if (managementNode.isVirtual()) {
            for (ManagementNode node : managementNode.getChildren()) {
                List<TreeNode> treeNodeList = checkPermAndConvertManagementNodeToTreeNode(node);
                if(treeNodeList != null){
                    result.addAll(treeNodeList);
                }
            }
        } else {
            TreeNode node = new TreeNode();
            node.setId(managementNode.getFullId());
            node.setText(managementNode.getName());


            if (managementNode.hasSubModule()) {
                for (ManagementNode sub : managementNode.getChildren()) {
                    List<TreeNode> subNode = checkPermAndConvertManagementNodeToTreeNode(sub);
                    if (subNode == null) {
                        continue;
                    }
                    for (TreeNode treeNode : subNode) {
                        node.addChildren(treeNode);
                    }
                }
            }

            boolean hasNodePerm = false;
            List<ModulePermission> permissions = managementNode.getPermissions();
            if (permissions != null) {
                for (ModulePermission p : permissions) {
                    //开发模式下将会赋予登录用户所有开放功能的功能权限
                    if (subject.isPermitted(managementNode.getFullId() + ":" + p.getCode())) {
                        hasNodePerm = true;
                        break;
                    }
                }
            }

            if ((permissions == null || permissions.isEmpty()) && !managementNode.hasSubModule()) {
                hasNodePerm = true;
            }

            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                node.setExpanded(true);
                node.setLeaf(false);
                hasNodePerm = true; //如果子菜单中有具有权限的项目则认为对父节点的功能可以访问
            } else if (hasNodePerm) {
                node.setLeaf(true);
                node.setHref(AppContext.getSiteBaseUrl() + "/admin/module_" + managementNode.getFullId() + ".do");
            }
            if (hasNodePerm) {
                result.add(node);
            } else {
                return null;
            }
        }
        return result;
    }

    @Override
    public Integer checkUserPassword(String email, String password) {
        AdminUserEntity uniqueResult = this.adminUserDao.getUniqueResult(
                "from AdminUserEntity c where u.email = ?", email);
        if (uniqueResult == null) {
            return null;
        }
        if (this.checkPassword(uniqueResult.getUserId(), password)) {
            return uniqueResult.getUserId();
        }
        return null;
    }

    @Override
    public boolean updateUserPassword(Integer userId, String oldPassword,
                                      String newPassword) {

        AdminUserEntity user = this.adminUserDao.getById(userId);
        boolean ok = this.checkPassword(user.getUserId(), oldPassword);
        if (ok) {
            user.setPassword(encryptPassword(user.getEmail(), newPassword));
            this.adminUserDao.update(user);
            return true;
        } else {
            throw new AppException("旧密码错误");
        }
    }

    public String encryptPassword(String email, String plainPassword) {
        return DigestUtils.md5Hex(email + plainPassword + email);
    }

    public boolean checkPassword(Integer userId, String inputPassword) {
        AdminUserEntity user = this.adminUserDao.loadById(userId);
        if (user == null) {
            return false;
        }
        String md5 = DigestUtils.md5Hex(user.getEmail() + inputPassword + user.getEmail());
        return user.getPassword().equals(md5);
    }

    @Override
    public boolean updateAdminUserRoles(Integer userId, Integer[] roleId) {
        //删除原有的角色
        this.adminUserRoleBindDao.deleteResultsByProperty("adminUserByUserId.userId", userId);
        this.adminUserRoleBindDao.flush();
        //添加新角色
        if (roleId != null) {
            AdminUserEntity user = this.adminUserDao.loadById(userId);
            for (Integer rId : roleId) {
                AdminRoleEntity adminRoleEntity = this.adminRoleDao.loadById(rId);
                AdminUserRoleBindEntity sysUserRole = new AdminUserRoleBindEntity();
                sysUserRole.setAdminRoleByRoleId(adminRoleEntity);
                sysUserRole.setCreatedByUserId(CurrentUser.get().getUserId());
                sysUserRole.setCreatedByRealName(CurrentUser.get().getRealName());
                sysUserRole.setCreatedAt(new Timestamp(System.currentTimeMillis()));
                sysUserRole.setAdminUserByUserId(user);
                this.adminUserRoleBindDao.save(sysUserRole);
            }
        }

        return true;
    }

    @Override
    public void updateLastLoginInfo(CurrentUser currentUser) {
        this.adminUserDao.updateProperty(currentUser.getUserId(), "lastLoginIp", currentUser.getLoginIp());
    }

    @Override
    public Map<Integer, String> getNicknameMap(Integer... userId) {


        if (userId != null && userId.length > 0) {
            String hql = "select userId,nickname from AdminUserEntity as u where u.userId in (" + StringUtils.join(userId, ",") + ")";

            List<Object[]> list = this.adminUserDao.findList(Object[].class, hql);

            if (list != null) {
                Map<Integer, String> nameMap = new HashMap<Integer, String>();
                for (Object[] s : list) {
                    nameMap.put(Integer.valueOf(s[0].toString()), s[1].toString());
                }

                return nameMap;
            }
        }

        return null;
    }

    @Override
    public Map<Integer, String> getRealNameMap(Integer... userId) {
        if (userId != null && userId.length > 0) {
            String hql = "select userId,realName from AdminUserEntity as u where u.userId in (" + StringUtils.join(userId, ",") + ")";

            List<Object[]> list = this.adminUserDao.findList(Object[].class, hql);

            if (list != null) {
                Map<Integer, String> nameMap = new HashMap<Integer, String>();
                for (Object[] s : list) {
                    nameMap.put(Integer.valueOf(s[0].toString()), s[1].toString());
                }

                return nameMap;
            }
        }

        return null;
    }

    @Override
    public boolean checkUserExistAndType(Integer userId, Integer userType) {
        String hql = "select userId from AdminUserEntity as u where u.userId = ? and u.userType = ?";
        long totalCount = this.adminUserDao.getTotalCount(hql, userId, userType);
        return totalCount > 0;
    }

    @Override
    public AdminUserVo getAdminUserById(Integer userId) {
        String hql = "select new "
                + AdminUserVo.class.getName()
                + "("
                + "u.userId,u.userType,u.email,u.password,u.nickname,u.openId,"
                + "u.realName,u.phone,u.gender,u.status,u.lastLoginIp,u.superman,u.createdAt,"
                + "u.createdByUserId,u.createdByRealName"
                + ") from AdminUserEntity as u where u.userId = ?";
        return this.adminUserDao.getUniqueResult(AdminUserVo.class, hql, userId);
    }

    @Override
    public Integer getUserIdByOpenId(String openId) {
        String hql = "select userId from AdminUserEntity as u where u.openId = ?";
        Integer id = this.adminUserDao.getUniqueResult(Integer.class, hql, openId);
        return id;
    }

    @Override
    public String getOpenIdById(Integer userId) {
        String hql = "select openId from AdminUserEntity as u where u.userId = ?";
        String openId = this.adminUserDao.getUniqueResult(String.class, hql, userId);
        return openId;
    }

    @Override
    public String getEmailById(Integer userId) {
        String hql = "select email from AdminUserEntity as u where u.userId = ?";
        String email = this.adminUserDao.getUniqueResult(String.class, hql, userId);
        return email;
    }

    @Override
    public boolean checkUserIsSuperMan(Integer userId) {
        String hql = "select superman from AdminUserEntity as u where u.userId = ?";
        Integer s = this.adminUserDao.getUniqueResult(Integer.class, hql, userId);
        return s == null ? false : s == 1 ? true : false;
    }

    @Override
    public void updateUserToEnabled(Integer userId) {
        this.adminUserDao.updateProperty(userId, "status", UserStatus.ENABLE_STATUS);
    }

    @Override
    public void updateUserToDisabled(Integer userId) {
        this.adminUserDao.updateProperty(userId, "status", UserStatus.DISABLED_STATUS);
    }

    @Override
    public void testTrasaction() {
        this.updateLastLoginInfo(CurrentUser.get());
        if (true) {
            throw new AppException("测试回滚");
        }
    }


    @Override
    public PageList<AdminUserVo> findByPage(Offset page, String likeRealName, String usertype) {
        String hql = "select new "
                + AdminUserVo.class.getName()
                + "("
                + "u.userId,u.userType,u.email,u.password,u.nickname,u.openId,"
                + "u.realName,u.phone,u.gender,u.status,u.lastLoginIp,u.superman,u.createdAt,"
                + "u.createdByUserId,u.createdByRealName"
                + ") from AdminUserEntity as u where u.superman=0 ";
        List<Object> params = new ArrayList();
        if (StringUtils.isNotEmpty(likeRealName)) {
            hql += " and u.realName like ?";
            params.add("%" + likeRealName + "%");
        } else if (StringUtils.isNotEmpty(usertype)) {
            hql += " and u.userType=?";
            params.add(Integer.valueOf(usertype));
        }
        return this.adminUserDao.findPageList(page, AdminUserVo.class, hql,
                params.toArray());
    }

    @Override
    public String getRealNameByUserId(Integer userId) {
        return this.adminUserDao.getPropertyById(userId, "realName", String.class);
    }

    /**
     * 通过userId查询Nickname
     *
     * @param userId
     * @return
     */
    @Override
    public String getNickNameByUserId(Integer userId) {
        return this.adminUserDao.getPropertyById(userId, "nickname", String.class);
    }

    @Override
    public UserSimpleVo getUserSimpleVo(Integer userId) {
        String hql = "select new " + UserSimpleVo.class.getName() + "(" +
                "u.userId," +
                "u.nickname," +
                "u.realName," +
                "u.email) " +
                "from AdminUserEntity as u where" +
                " u.userId = ?";
        return this.adminUserDao.getUniqueResult(UserSimpleVo.class, hql, userId);
    }

    @Override
    public List<UserSimpleVo> findUserSimpleVoByUserType(Integer userType, String name) {

        List<Object> params = new ArrayList<Object>();

        String hql = "select new " + UserSimpleVo.class.getName() + "(" +
                "u.userId," +
                "u.nickname," +
                "u.realName," +
                "u.email) " +
                "from AdminUserEntity as u where 1=1";


        if (userType != null) {
            hql += " and u.userType = ?";
            params.add(userType);
        }
        if (StringUtils.isNotBlank(name)) {
            hql += " and " +
                    "(u.nickname like ?" +
                    " or u.realName like ?)";
            params.add("%" + name + "%");
            params.add("%" + name + "%");
        }

        hql += " order by u.nickname";
        return adminUserDao.findList(UserSimpleVo.class, hql, params);
    }


}
